<?php
namespace app\api\controller;
use think\Controller;
use think\Session;
use think\Db;

class Active extends Controller {
    //根据卡号用积分兑换券
	public function exchange(){
		$apilog = new Common();
		//手机号
		$mobile = input('mobile',session('userinfo.Mobile'));
		//活动id 
		$action_id = input('actionId');
		//券id 
		$couponId = input('couponId');
		//扣减积分值
//		$point = input('point');
		//会员卡号
		$cardhyno = input('CardHyNo');
		//会员名称
		$username = input('username',session('userinfo.UserName'));
		//卡级
		$cardLevel = input('cardLevel',session('userinfo.MallCardName'));
		//查询用户券领取数量
		$gotCouponNum = Db::name('exchange')
			->where('coupon_id',$couponId)
			->where('mobile',$mobile)
			->where('status',1)
			->count();
		//查券剩余库存
		$coupon = Db::name('coupon')
			->where('id',$couponId)
			->lock(true)
			->find();
		//查看用户领取是否达到限制
		if($gotCouponNum >= $coupon['people_num']){
			rtnError('此券您已达到最大领取数量',$coupon['real_stock']);
		}
		//库存不足,停止
		if($coupon['real_stock']<=0){
			rtnError('此券库存不足',$coupon['real_stock']);
		}
		//有库存，库存先减一（加锁）
		$couponReal = Db::name('coupon')
			->where('id',$couponId)
    		->setDec('real_stock', 1);
    	//扣减积分值
		$point = $coupon['point'];
		//促销单号
		$cxbillno = $coupon['promotion_num'];
		//券备注
		$cxremark = $coupon['cxremark'];
		//面值
		$certime = $coupon['certime'];
    	//扣减积分
    	$sendResult = $this->decScore($cardhyno,$point);
    	if($sendResult){
    		//扣减积分成功
    	}else {
    		//扣减积分失败，库存加一
			$couponReal = Db::name('coupon')
				->where('id',$couponId)
	    		->setInc('real_stock', 1);
    		//扣减积分失败，终止
			rtnError('积分扣减失败',$sendResult);
    	}
		//获取最后一条记录的赠券号（加锁，阻止其他人查询）
		$certino = $this->creatCertino($couponId);
		//插入领券记录数据
		$exchange = [
	    	'mobile' => $mobile,
	    	'coupon_id' => $couponId,
	    	'gettime' => date('Y-m-d H:i:s'),
	    	'username' => $username,
	    	'point' => $point,
	    	'cardHyNo' => $cardhyno,
	    	'certino' => $certino,
	    	'cardLevel' => $cardLevel,
	    	'action_id' => $action_id
	    ];
	    try{
	    	//添加一条 未发送 状态的 发券记录
	    	$exchangeId = Db::name('exchange')
				->insertGetId($exchange);
	    }catch (\Exception $e){
	    	//发送失败库存，库存加一
			$couponReal = Db::name('coupon')
				->where('id',$couponId)
	    		->setInc('real_stock', 1);
			rtnError('系统繁忙，请稍后再试',$e);
       	}

//		$certino = $certino.rand(10000,99999);
		//校验码，4位随机数
		$rand = rand(1000, 9999);
		$postData = array(
			'CXBILLNO' => $cxbillno, // ————促销单号（后台配置）
			'CERTINO' => $certino, //  ————赠券号（传入时我方生成，赠券号以89开头 89yymmdd12345后面是2位年月日然后是5位顺序码，举例0018042300001 ）
			'CHECKCODE' => $rand, //校验码  qd.hisense.sylwtech.cn
			'CERTIME' => $certime, //  ————面值   lucky_girls_day 
			'CXREMARK' => $cxremark, // ————备注（相当于券说明，后台传入）K5LcxCcBmkKZ8YKw
			'CARDHYNO' => session('userinfo.ThirdPartyCardNo'), // ————会员卡 卡面号
			'WEIXININFO' => '', 'USBGNDATE' => '', 'USENDDATE' => ''
		);
		//发券123.235.28.142：8082
		$url = "http://123.235.28.142:8082/ApplyCertiForeign01.asmx";
		$SOAPAction = "http://tempuri.org/ApplyCertiForeign01Func";
		$data = '<?xml version="1.0" encoding="utf-8"?>
			<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
			  <soap:Body>
			    <ApplyCertiForeign01Func xmlns="http://tempuri.org/">
			      <sjson>['.json_encode($postData).']</sjson>
			      <UserId>10020000051158</UserId>
			      <PassWord>108F12E9AEF9203E</PassWord>
			    </ApplyCertiForeign01Func>
			  </soap:Body>
			</soap:Envelope>';
		$result = $this->GetYktEmpInfo($url,$data,$SOAPAction);
		
		//检查错误，获取返回值
		if ($result) {
			$sendTime = date('Y-m-d H:i:s');
			$jsonstr = $result->ApplyCertiForeign01FuncResponse->ApplyCertiForeign01FuncResult;
			$domain = strstr($jsonstr, "'1'");
			
			
			if ($domain == false) {
				//领券失败，日志
				$apilog->dataFormat($data,$jsonstr,'/api/Active/exchange',$jsonstr,"xml","领取券接口失败");
				rtnError('领券失败',2);
			} else {
				//领券成功，日志
				$apilog->dataFormat($data,$jsonstr,'/api/Active/exchange',$jsonstr,"xml","领取券接口成功");
				Db::name('exchange')
					->where('id',$exchangeId)
					->update(['status'=>1]);
				rtnSuccess('兑换成功');
//				return json_encode([
//					'exchangeId' => $exchangeId,
//					'msg' => 'success'
//				]);
			}
		} else {
			//接口调用失败，日志
			$apilog->dataFormat($data,$result,'/api/Active/exchange',$result,"xml","领取券接口失败");
			rtnError('领券失败',3);
		}
	}
	
	//扣除积分
    public function decScore($card,$point){
		$apilog = new Common();
    	$postData = [
    		'card' => $card,
    		'score' => $point
    	];
        $sign = json_decode($this->connectMysql());
        $guid = $sign->workGuid;
        $key = $sign->key;
        // 输入报文中的随机整数，目的是为了使报文的长度不固定，从而影响加密结果以混淆报文
        $random = rand ( 0, 99 );
        // 输入报文格式
        $body = '<?xml version="1.0" encoding="UTF-8"?>
            <InputParameter>
                <RandomNo>'.$random.'</RandomNo>
                <UserCode>qdxx08</UserCode>
                <WorkGuid>'.$guid.'</WorkGuid>
                <OrgCode>1008</OrgCode>
                <POSNo>001</POSNo>
                <CardNoType>2</CardNoType>
                <CardNo>'.$card.'</CardNo>
                <PrjCode>2001</PrjCode>
                <OldBillNo>'.time().rand(100000,999999).'</OldBillNo>
                <Remark></Remark>
                <FlType>0</FlType>
                <BillType>1</BillType>
                <BillNo></BillNo>
                <DepCode>01</DepCode>
                <TerminalNo></TerminalNo>
                <ComputerName></ComputerName>
                <FlKind>0</FlKind>
                <SFlJfTotal>'.$point.'</SFlJfTotal>
                <SFlTotal></SFlTotal>
            </InputParameter>';
        //echo $body;die;
//		dump($body);
		$inParam = $body;
        require_once("Java.inc");
        $des = new \Java('RSAEncrpt.DES3');

        $body = $des->encrypt($body,$key);
        $tag = strtoupper(md5($body.'ABCD'));
        $para = '<?xml version="1.0" encoding="UTF-8" ?>
            <InputParameter>
                <Head><ClientCode>001</ClientCode><Tag>'.$tag.'</Tag></Head>
                <Body>'.$body.'</Body>
            </InputParameter>';
//		dump($para);
        $client = new \SoapClient("http://60.30.83.101:1144/HisComSvr/HsCRMWebSrv.dll/wsdl/IHsCRMWebSrv?wsdl");
        $output = $client->IWsPosCommOperate ( '107', $para );
        if ($output->ReturnCode == 0){
            $rstXml = $des->decrypt($output->OutputPara,$key);
            $rst = xmlToArray($rstXml);
			$apilog->dataFormat($inParam,$rst,'/api/Active/decScore',$rstXml,"xml","扣减积分接口成功");
            return json_encode($rst);
        } else {
        	//接口调用失败，日志
        	$errMsg = iconv("GBK","UTF-8", base64_decode($output->RtnMsg));
			$apilog->dataFormat($inParam,$errMsg,'/api/Active/decScore',$errMsg,"xml","扣减积分接口失败");
//		    echo iconv("GBK","UTF-8", base64_decode($output->RtnMsg));
			return false;
        }
    }
    //生成赠券号
    public function creatCertino($couponId){
    	$findOrder = Db::name('exchange')
    		->lock(true)
			->order("id desc")
			->field("id,certino")
			->select();
		//生成赠券号
		$dateTime = date("ymd");
		if (empty($findOrder)) {
			$order = "00001";
			$certino = "89" . $dateTime . $order;
		} else {
			$certino = $findOrder[0]['certino'];
			$order = substr($certino, -5) + 1;
			$if = strlen($order);
			if ($if < 5) {
				for ($i = 0; $i = 5 - strlen($order); $i++) {
					$order = "0" . $order;
				}
			}
			$certino = "89" . $dateTime . $order;
		}
		return $certino;
    }
    //跨数据库读数据
    public function connectMysql(){
    	$result = Db::connect('db_saas');
    	$sign = $result->table('sylw_zapi1_actionlist')->where("id","=",1)->find();
		$data = [
			'guid' => $sign['workGuid'],
            'key' => $sign['key']
		];
		return json_encode($sign);
    }
    //添加活动点击记录
    public function actionClick(){
    	$action_id = input("actionId");
    	$mobile = input("mobile");
    	$addData = [
    		'action_id' => $action_id,
    		'mobile' => $mobile,
    		'hittime' => date("Y-m-d H:i:s")
    	];
    	$insertId = Db::name('action_hit')
    		->insertGetId($addData);
    	rtnSuccess('点击成功',$insertId,1);
    }
    
    //测试高并发
    public function testSend(){
		$redis=new \Redis();
        $connectredis = $redis->connect(config('redis.REDIS_HOST'),config("redis.REDIS_PORT"));       
       	$CardHyNo='54976'.rand(10,99);
		$username='测试用户'.rand(10,99);
		$mobile='1501234'.rand(0000,9999);
		$couponId=3;
		$cardLevel='准会员';
		$actionId=1;
		$point = 0.01;
		$sendNumber = 0;
		for($i = 0;$i<120;$i++){
			$this->addlock($couponId);
			$re = $this->exchange($username,$mobile,$CardHyNo,$cardLevel,$couponId,$actionId,$point);
			$this->dellock($couponId);
			$sendNumber++;
		}
		return $sendNumber;
    }
    
    /*
     	加锁
     * */
    public function addlock($couponId){
    	$redis=new \Redis();
        $connectredis = $redis->connect(config('redis.REDIS_HOST'),config("redis.REDIS_PORT"));       
       	$lock_key = 'LOCK_PREFIX' . $couponId;
		$is_lock = $redis->setnx($lock_key, 1); // 加锁
		return $is_lock;
    }
    /*
     	释放锁
     * */
    public function dellock($couponId){
    	$redis=new \Redis();
        $connectredis = $redis->connect(config('redis.REDIS_HOST'),config("redis.REDIS_PORT"));       
       	$lock_key = 'LOCK_PREFIX' . $couponId;
		$redis->del($lock_key);
		return;
    }
    
    /**
        * redis连接
        * @access private
        * @return resource
        * @author bieanju
        */
    public function connectRedis(){
        $redis=new \Redis();
        $connectredis = $redis->connect(config('redis.REDIS_HOST'),config("redis.REDIS_PORT"));       
        return json_encode($connectredis);
    }
    
    public function GetYktEmpInfo($url, $data = '', $SOAPAction = '') {
		$respose = $this->reqpost($url, $data, $SOAPAction);
		$respose = str_replace("soap:", "", $respose);
		$xml = simplexml_load_string($respose);
		$data = $xml -> Body;
		return $data;
	}
	
	public function reqpost($url, $post_data = '', $SOAPAction = '') {
		$ch = curl_init();
		curl_setopt($ch, CURLINFO_HEADER_OUT, TRUE);
		$headers = array("Content-type:text/xml; charset=utf-8", "SOAPAction:" . $SOAPAction);
		curl_setopt($ch, CURLOPT_URL, $url);
		curl_setopt($ch, CURLOPT_POST, true);
		curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
		curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
		curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 15);
		curl_setopt($ch, CURLOPT_HEADER, false);
		$file_contents = curl_exec($ch);
		$a = curl_getinfo($ch);
		return $file_contents;
	}
}
